home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / heap / localam.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  7.5 KB  |  338 lines

  1. /*
  2.  * localam.c --
  3.  *    POSTGRES heap access method "fast" code for temp or "retrieve into"
  4.  *  relations.  NOTE:  Since these relations are not visible to anyone but
  5.  *  the backend that is generating them, this code completely ignores the
  6.  *  multi-user buffer pool and utilities, and is optimized for fast appends.
  7.  *
  8.  *  ! DO NOT USE THIS CODE FOR ANYTHING BUT TEMP OR "RETRIEVE INTO" RELATIONS !
  9.  */
  10.  
  11. #include <sys/file.h>
  12.  
  13. #include "tmp/c.h"
  14.  
  15. RcsId("$Header: /private/postgres/src/access/heap/RCS/localam.c,v 1.8 1992/07/13 03:09:29 hong Exp $");
  16.  
  17. #include "access/heapam.h"
  18. #include "access/hio.h"
  19. #include "access/htup.h"
  20. #include "access/xact.h"
  21.  
  22. #include "storage/block.h"
  23. #include "storage/buf.h"
  24. #include "storage/bufmgr.h"
  25. #include "storage/bufpage.h"
  26. #include "storage/itemid.h"
  27. #include "storage/itemptr.h"
  28.  
  29. #include "utils/memutils.h"
  30. #include "utils/log.h"
  31. #include "utils/rel.h"
  32.  
  33.  
  34. typedef struct l_rellist
  35. {
  36.     Relation relation;
  37.  
  38.     Page read_page, write_page;
  39.     BlockNumber read_blocknum, write_blocknum;
  40.  
  41.     OffsetIndex offset_index;
  42.     bool active;
  43.     struct l_rellist *next;
  44. }
  45. LocalRelList;
  46.  
  47. LocalRelList *head = NULL, *current = NULL, *tail = NULL;
  48. LocalRelList *GetRelListEntry(), *AddToRelList(); 
  49.  
  50. /*
  51.  * Public interface routines:
  52.  */
  53.  
  54. local_heap_close(relation)
  55.  
  56. Relation relation;
  57.  
  58. {
  59.     LocalRelList *p = GetRelListEntry(relation);
  60.     if (p->write_page != NULL) WriteLocalPage(p);
  61.     DeleteRelListEntry(relation);
  62. }
  63.  
  64. local_heap_destroy(relation)
  65.  
  66. Relation relation;
  67.  
  68. {
  69.     LocalRelList *p = GetRelListEntry(relation);
  70.     FileUnlink(p->relation->rd_fd);
  71. }
  72.  
  73. local_heap_open(relation)
  74.  
  75. Relation relation;
  76.  
  77. {
  78.     MemoryContext    oldCxt;
  79.     MemoryContext    portalContext;
  80.     Portal         portal;
  81.  
  82.     /* ----------------
  83.      *    get the blank portal and its memory context
  84.      * ----------------
  85.      */
  86.     portal = GetPortalByName(NULL);
  87.     portalContext = (MemoryContext) PortalGetHeapMemory(portal);
  88.  
  89.     oldCxt = MemoryContextSwitchTo(portalContext);
  90.     AddToRelList(relation);
  91.     (void) MemoryContextSwitchTo(oldCxt);
  92. }
  93.  
  94. void
  95. local_heap_insert(relation, tup)
  96.     Relation    relation;
  97.     HeapTuple    tup;
  98. {
  99.     /* ----------------
  100.      *    increment access statistics
  101.      * ----------------
  102.      */
  103.     IncrHeapAccessStat(local_insert);
  104.     IncrHeapAccessStat(global_insert);
  105.  
  106.     if (!ObjectIdIsValid(tup->t_oid)) {
  107.         tup->t_oid = newoid();
  108.         LastOidProcessed = tup->t_oid;
  109.     }
  110.  
  111.     TransactionIdStore(GetCurrentTransactionId(), &(tup->t_xmin));
  112.     tup->t_cmin = GetCurrentCommandId();
  113.     PointerStoreInvalidTransactionId((Pointer)&(tup->t_xmax));
  114.     tup->t_tmin = InvalidTime;
  115.     tup->t_tmax = InvalidTime;
  116.  
  117.     local_doinsert(relation, tup);
  118. }
  119.  
  120. /*
  121.  * These routines are called by the transaction manager.  They are useful
  122.  * in cleaning up dead temp relations and such from an AbortTransaction
  123.  * or an elog(WARN).  They do not completely solve the problem of dead
  124.  * tmp relations, however; we have to do something about those left over from
  125.  * a crashed backend.
  126.  */
  127.  
  128. AtAbort_LocalRels()
  129.  
  130. {
  131.     DestroyLocalRelList();
  132. }
  133.  
  134. AtCommit_LocalRels()
  135.  
  136. {
  137.     DestroyLocalRelList();
  138. }
  139.  
  140. /*
  141.  * Private routines
  142.  */
  143.  
  144. LocalRelList *
  145. AddToRelList(relation)
  146.  
  147. Relation relation;
  148.  
  149. {
  150.     if (tail == NULL)
  151.     {
  152.         Assert(head == NULL);
  153.         head = (LocalRelList *) palloc(sizeof(LocalRelList));
  154.         tail = head;
  155.     }
  156.     else
  157.     {
  158.         tail->next = (LocalRelList *) palloc(sizeof(LocalRelList));
  159.         tail = tail->next;
  160.     }
  161.  
  162.     tail->relation = relation;
  163.     tail->read_page = tail->write_page = NULL;
  164.     tail->read_blocknum = tail->write_blocknum = 0;
  165.     tail->offset_index = 0;
  166.     tail->next = NULL;
  167.     tail->active = true;
  168.     current = tail;
  169.     return(tail);
  170. }
  171.  
  172. LocalRelList *
  173. GetRelListEntry(relation)
  174.  
  175. Relation relation;
  176.  
  177. {
  178.     LocalRelList *p;
  179.  
  180.     Assert(current != NULL);
  181.     if (current->relation == relation) return(current);
  182.  
  183.     for (p = head; p != NULL && p->relation != relation; p = p->next);
  184.  
  185.     if (p == NULL) elog(WARN, "GetRelListEntry: can't find rel in list!");
  186.     return(p);
  187. }
  188.  
  189. /*
  190.  * This does not do an actual list delete, but instead marks the list
  191.  * entry as inactive and frees its page.  This is done so that all the
  192.  * temp relations can be saved and blown away at TransactionAbort time
  193.  * if necessary by a call to DestroyLocalRelList.
  194.  */
  195.  
  196. DeleteRelListEntry(relation)
  197.  
  198. Relation relation;
  199.  
  200. {
  201.     LocalRelList *p;
  202.  
  203.     Assert(head != NULL);
  204.  
  205.     for (p = head; p != NULL && p->relation != relation; p = p->next);
  206.  
  207.     Assert(p != NULL);
  208.  
  209.     p->active = false;
  210.  
  211.     /* don't waste excessive memory */
  212.  
  213.     if (p->read_page != NULL) pfree(p->read_page);
  214.  
  215.     if (p->write_page != NULL) pfree(p->write_page);
  216.  
  217.     p->read_page = p->write_page = NULL;
  218.  
  219.     if (current == p)
  220.     {
  221.         for (p = head; p->next != NULL && ! p->active; p = p->next);
  222.  
  223.         if (p->next == NULL) current = NULL;
  224.         else current = p;
  225.     }
  226. }
  227.  
  228. /*
  229.  * This routine is useful for AbortTransaction - it deletes the temp
  230.  * relations in the list if they are still active.  They should not ever
  231.  * be active at TransactionCommit time, although this routine needs to
  232.  * be called at the end of a transaction no matter what happens.
  233.  */
  234.  
  235. DestroyLocalRelList()
  236.  
  237. {
  238.     LocalRelList *p, *q;
  239.     for (p = head; p != NULL; p = q)
  240.     {
  241.         if (p->active)
  242.         {
  243.             FileUnlink(p->relation->rd_fd);
  244.             if (p->read_page != NULL) pfree(p->read_page);
  245.             if (p->write_page != NULL) pfree(p->write_page);
  246.         }
  247.         q = p->next;
  248.         pfree(p);
  249.     }
  250.     head = current = tail = NULL;
  251. }
  252.  
  253. local_doinsert(relation, tuple)
  254.  
  255. Relation relation;
  256. HeapTuple tuple;
  257.  
  258. {
  259.     LocalRelList *rel_info;
  260.     Size len = LONGALIGN(tuple->t_len);
  261.     OffsetIndex offsetIndex;
  262.     ItemId      itemId;
  263.     HeapTuple   page_tuple;
  264.  
  265.     rel_info = GetRelListEntry(relation);
  266.  
  267.     if (rel_info->write_page == NULL)
  268.     {
  269.         rel_info->write_page = (Page) palloc(BLCKSZ);
  270.         PageInit(rel_info->write_page, BLCKSZ, 0);
  271.     }
  272.  
  273.     if (len > PageGetFreeSpace(rel_info->write_page))
  274.     {
  275.         WriteLocalPage(rel_info);
  276.         rel_info->write_blocknum++;
  277.         bzero(rel_info->write_page, BLCKSZ);
  278.         PageInit(rel_info->write_page, BLCKSZ, 0);
  279.     }
  280.  
  281.     offsetIndex = PageAddItem((Page)rel_info->write_page, (Item)tuple,
  282.                               tuple->t_len, InvalidOffsetNumber, LP_USED) - 1;
  283.  
  284.     itemId = PageGetItemId((Page)rel_info->write_page, offsetIndex);
  285.  
  286.     page_tuple = (HeapTuple) PageGetItem(rel_info->write_page, itemId);
  287.  
  288.     /*
  289.      * As this code is being used for "retrieve into" or tmp relations, 
  290.      * the RuleLock can be set to invalid as no tuple rule can exist on
  291.      * such relations.
  292.      */
  293.  
  294.     page_tuple->t_locktype = DISK_RULE_LOCK;
  295.     ItemPointerSetInvalid(&page_tuple->t_lock.l_ltid);
  296.  
  297.     ItemPointerSimpleSet(&page_tuple->t_ctid,
  298.                          rel_info->write_blocknum,
  299.                          1 + offsetIndex);
  300. }
  301.  
  302. WriteLocalPage(rel_info)
  303.  
  304. LocalRelList *rel_info;
  305.  
  306. {
  307.     unsigned long offset;
  308.     int nbytes;
  309.  
  310.     offset = rel_info->write_blocknum * BLCKSZ;
  311.  
  312.     FileSeek(rel_info->relation->rd_fd, offset, L_SET);
  313.  
  314.     nbytes = FileWrite(rel_info->relation->rd_fd,
  315.                        (char *) rel_info->write_page,
  316.                        BLCKSZ);
  317.  
  318.     Assert(nbytes == BLCKSZ);
  319. }
  320.  
  321. ReadLocalPage(rel_info)
  322.  
  323. LocalRelList *rel_info;
  324.  
  325. {
  326.     unsigned long offset;
  327.     int nbytes;
  328.  
  329.     offset = rel_info->read_blocknum * BLCKSZ;
  330.  
  331.     FileSeek(rel_info->relation->rd_fd, offset, L_SET);
  332.  
  333.     nbytes = FileRead(rel_info->relation->rd_fd,
  334.                        (char *) rel_info->read_page,
  335.                        BLCKSZ);
  336.     return(nbytes);
  337. }
  338.